package be.nepherte.movmanager.server;

import java.util.ArrayList;
import java.util.List;
import net.sf.gilead.adapter4appengine.EngineRemoteService;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import be.nepherte.movmanager.client.services.MovieService;
import be.nepherte.movmanager.client.services.MovieServiceAsync;
import be.nepherte.movmanager.client.exceptions.MovieAlreadyExistsException;
import be.nepherte.movmanager.client.exceptions.MovieNotInCollectionException;
import be.nepherte.movmanager.client.exceptions.NotLoggedInException;
import be.nepherte.movmanager.domain.Movie;
import be.nepherte.movmanager.domain.MovieCollection;
import be.nepherte.movmanager.domain.UserInfo;
import be.nepherte.movmanager.server.util.PersistenceContext;

/**
 * <p>
 * This class is the server side implementation for movie related services. 
 * Apart from a server side implementation, a client side asynchronous version,
 * {@link MovieServiceAsync}, and a client side stub, {@link MovieService} is
 * required as well. The used communication protocol is Google's implementation
 * of rpc.
 * </p>
 * 
 * <p>
 * Copyright © 2010 Bart Verhoeven
 * </p>
 * 
 * <p>
 * This file is part of MovManager.
 * </p>
 * 
 * <p>
 * MovManager is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * </p>
 * 
 * <p>
 * MovManager is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * </p>
 * 
 * <p>
 * You should have received a copy of the GNU General Public License along with
 * MovManager. If not, see http://www.gnu.org/licenses/.
 * </p>
 * 
 * @author 	Bart Verhoeven
 * @version 0.1
 */
public class MovieServiceImpl extends EngineRemoteService implements MovieService {
	private static final long serialVersionUID = 1L;
	
	@Override
	public Movie storeMovie(Movie movie, UserInfo userInfo) throws MovieAlreadyExistsException, NotLoggedInException {
		if (!userInfo.isLoggedIn())
			throw new NotLoggedInException("The user is not logged in.");
		
		PersistenceManager persistenceManager = null;
		MovieCollection collection = null;
		
		try {
			persistenceManager = PersistenceContext.getPersistenceManagagerFactory().getPersistenceManager();
			
			// construct query: movie collection associated with the user's id
			Query q = persistenceManager.newQuery(MovieCollection.class);
			q.setFilter("userId == id");
			q.declareParameters("String id");
			
			try  {
				List<?> result = (List<?>) q.execute(userInfo.getId());
				
				// if no collection exists, create one and store movies
				// if collection exists, append the movies to the collection
				if (result.isEmpty()) {
					collection = new MovieCollection(userInfo.getId());
					collection.addMovie(movie);
					persistenceManager.makePersistent(collection);
				} else {
					collection = (MovieCollection) result.get(0);
					collection.addMovie(movie);
				}
			} finally {
				q.closeAll();
			}
			
			return (Movie) persistenceManager.detachCopy(movie);
		} finally {
			if (persistenceManager != null)
				persistenceManager.close();
		}
	}
	
	@Override
	public void editMovie(Movie movie, UserInfo userInfo) throws NotLoggedInException, MovieNotInCollectionException {
		if (!userInfo.isLoggedIn())
			throw new NotLoggedInException("The user is not logged in.");
		
		if (movie.getKey() == null)
			throw new MovieNotInCollectionException("Movie " + movie.getTitle() + "does not belong to a movie collection.");
		
		PersistenceManager persistenceManager = null;
		
		try {
			persistenceManager = PersistenceContext.getPersistenceManagagerFactory().getPersistenceManager();
			persistenceManager.makePersistent(movie);
		} finally {
			if (persistenceManager != null)
				persistenceManager.close();
		}
	}
	

	@Override
	public List<Movie> getMovies(UserInfo userInfo) throws NotLoggedInException {
		if (!userInfo.isLoggedIn())
			throw new NotLoggedInException();
		
		PersistenceManager persistenceManager = null;
		List<Movie> movies = new ArrayList<Movie>();
		
		try {
			persistenceManager = PersistenceContext.getPersistenceManagagerFactory().getPersistenceManager();
			
			// construct query: movie collection associated with the user's id
			Query q = persistenceManager.newQuery(MovieCollection.class);
			q.setFilter("userId == id");
			q.declareParameters("String id");

			try {
				List<?> result =  (List<?>) q.execute(userInfo.getId());
				
				// since user id is a unique value, taking the first result from the result set is correct
				if (result != null && !result.isEmpty())
					movies =  ((MovieCollection)result.get(0)).getMovieCollection();	
			} finally {
				q.closeAll();
			}
			return (List<Movie>) persistenceManager.detachCopyAll(movies);
		} finally {
			if(persistenceManager != null)
				persistenceManager.close();
		}
	}
}
